package com.parking.mgr.common.error;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpStatus;
import com.parking.mgr.common.constant.CommonConstant;
import com.parking.mgr.common.constant.SysExpEnumConstant;
import com.parking.mgr.common.enums.LoginStatusEnums;
import com.parking.mgr.common.enums.NeedLoginStatusEnums;
import com.parking.mgr.common.exception.LoginAuthException;
import com.parking.mgr.common.exception.LoginVerifyException;
import com.parking.mgr.common.exception.ServiceException;
import com.parking.mgr.common.exception.enums.PermissionExceptionEnum;
import com.parking.mgr.common.exception.enums.ServerExceptionEnum;
import com.parking.mgr.common.pojo.login.LoginStatus;
import com.parking.mgr.common.pojo.response.Failures;
import com.parking.mgr.common.pojo.response.Result;
import com.parking.mgr.common.util.MessageUtils;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.context.request.WebRequest;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @ClassName CommonErrorAttributes
 * @Description 将系统管理未知错误异常，输出格式重写为我们熟悉的响应格式
 * @author: zhijianpu
 * @Date: 2025/2/28
 */
public class CommonErrorAttributes extends DefaultErrorAttributes {

    @Override
    public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions attributeOptions) {
        // 1. 先获取spring默认的返回内容
        Map<String, Object> defaultErrorAttributes = super.getErrorAttributes(webRequest, attributeOptions);

        // 2. 如果返回的异常是ServiceException，则按ServiceException响应的内容进行返回
        Throwable throwable = this.getError(webRequest);
        // 服务异常
        if (throwable instanceof ServiceException) {
            ServiceException serviceException = (ServiceException) throwable;
            List<Failures> failuresList = new ArrayList<>();
            failuresList.add(new Failures(SysExpEnumConstant.DEFAULT_ERROR_CODE, CommonConstant.OPERATION_FAILURE));
            failuresList.add(new Failures(serviceException.getCode(), serviceException.getMessage(), serviceException.getMessage()));
            return BeanUtil.beanToMap(Result.error(serviceException.getMessage(),
                    new LoginStatus(LoginStatusEnums.LOGIN_STATE.getCode(), NeedLoginStatusEnums.NEED_LOGIN.getCode()), failuresList));
        }

        // 登录授权异常
        if (throwable instanceof LoginAuthException) {
            LoginAuthException loginAuthException = (LoginAuthException) throwable;
            List<Failures> failuresList = new ArrayList<>();
            failuresList.add(new Failures(SysExpEnumConstant.DEFAULT_ERROR_CODE, CommonConstant.OPERATION_FAILURE));
            failuresList.add(new Failures(loginAuthException.getCode(), loginAuthException.getMessage(), loginAuthException.getMessage()));
            return BeanUtil.beanToMap(Result.error(loginAuthException.getCode(), loginAuthException.getMessage(),
                    new LoginStatus(LoginStatusEnums.NO_LOGIN_STATE.getCode(), NeedLoginStatusEnums.NEED_LOGIN.getCode()), failuresList));
        }

        // 登录验证异常
        if (throwable instanceof LoginVerifyException) {
            LoginVerifyException loginVerifyException = (LoginVerifyException) throwable;
            List<Failures> failuresList = new ArrayList<>();
            failuresList.add(new Failures(SysExpEnumConstant.DEFAULT_ERROR_CODE, CommonConstant.OPERATION_FAILURE));
            failuresList.add(new Failures(loginVerifyException.getCode(), loginVerifyException.getMessage(), loginVerifyException.getMessage()));
            return BeanUtil.beanToMap(Result.error(205, loginVerifyException.getMessage(),
                    new LoginStatus(LoginStatusEnums.LOGIN_STATE.getCode(), NeedLoginStatusEnums.NEED_LOGIN.getCode()), failuresList));
        }

        // 3.如果返回的是404 http状态码
        Integer status = (Integer) defaultErrorAttributes.get("status");
        if (status.equals(HttpStatus.HTTP_NOT_FOUND)) {
            List<Failures> failuresList = new ArrayList<>();
            failuresList.add(new Failures(SysExpEnumConstant.DEFAULT_ERROR_CODE, CommonConstant.OPERATION_FAILURE));
            failuresList.add(new Failures(PermissionExceptionEnum.URL_NOT_EXIST.getCode(), PermissionExceptionEnum.URL_NOT_EXIST.getMessage(), PermissionExceptionEnum.URL_NOT_EXIST.getMessage()));
            return BeanUtil.beanToMap(Result.error(PermissionExceptionEnum.URL_NOT_EXIST.getCode(),
                    PermissionExceptionEnum.URL_NOT_EXIST.getMessage(),
                    new LoginStatus(LoginStatusEnums.LOGIN_STATE.getCode(), NeedLoginStatusEnums.NEED_LOGIN.getCode()),
                    failuresList));
        }


        // 4.如果返回的是400
        if (status.equals(HttpStatus.HTTP_BAD_REQUEST)) {
            if (throwable instanceof MethodArgumentNotValidException) {
                MethodArgumentNotValidException methodArgumentNotValidException = (MethodArgumentNotValidException) throwable;
                if (methodArgumentNotValidException.getBindingResult().hasErrors()) {
                    List<ObjectError> errorList =  methodArgumentNotValidException.getBindingResult().getAllErrors();
                    List<Failures> failuresList = new ArrayList<>();
                    failuresList.add(new Failures(SysExpEnumConstant.DEFAULT_ERROR_CODE, CommonConstant.OPERATION_FAILURE));
                    for (ObjectError error : errorList) {
                        failuresList.add(new Failures(CommonConstant.VALIDATED_DATA_EXP_CODE, error.getDefaultMessage(), error.toString()));
                    }
                    //methodArgumentNotValidException.getBindingResult().getAllErrors();
                    return BeanUtil.beanToMap(Result.error(CommonConstant.OPERATION_FAILURE, new LoginStatus(LoginStatusEnums.LOGIN_STATE.getCode(), NeedLoginStatusEnums.NEED_LOGIN.getCode()),
                            failuresList));
                }
            }

        }


        // 5.无法确定的返回服务器异常
        List<Failures> failuresList = new ArrayList<>();
        failuresList.add(new Failures(SysExpEnumConstant.DEFAULT_ERROR_CODE, CommonConstant.OPERATION_FAILURE));
        String defaultMessage = throwable.getMessage();
        if (defaultErrorAttributes.containsKey("message")) {
            failuresList.add(new Failures(ServerExceptionEnum.SERVER_ERROR.getCode(), MessageUtils.message(ServerExceptionEnum.I18N_MESSAGE_SERVER_ERROR.getMessage(),
                    ServerExceptionEnum.SERVER_ERROR.getMessage()),
                    defaultMessage));
        } else {
            failuresList.add(new Failures(ServerExceptionEnum.SERVER_ERROR.getCode(),
                    MessageUtils.message(ServerExceptionEnum.I18N_MESSAGE_SERVER_ERROR.getMessage(), ServerExceptionEnum.SERVER_ERROR.getMessage()), defaultMessage));
        }

        return BeanUtil.beanToMap(Result.error(ServerExceptionEnum.SERVER_ERROR.getCode(),
                MessageUtils.message(ServerExceptionEnum.SERVER_ERROR.getMessage(), ServerExceptionEnum.I18N_MESSAGE_SERVER_ERROR.getMessage()),
                new LoginStatus(LoginStatusEnums.LOGIN_STATE.getCode(), NeedLoginStatusEnums.NEED_LOGIN.getCode()),
                failuresList));
    }
}
